﻿using System;
using System.Windows.Input;
using System.Windows;

namespace Redbrick.Silverlight
{

    public class CommandArgs : EventArgs
    {
        public CommandArgs(object parameter)
        {
            this.Parameter = parameter;
        }

        public object Parameter { get; private set; }
        public bool Handled{get;set;}
        public UIElement HandledBy { get; set; }
    }

    public class DelegateCommand : ICommand
    {

        #region Declarations

        Func<object, bool> _canExecute;
        Action<object> _executeAction;

        #endregion Declarations

        #region Constructor

        public DelegateCommand() : this(null, (p) => true) { }
        public DelegateCommand(Action<object> executeAction)
            : this(executeAction, null)
        {
        }

        public DelegateCommand(Action<object> executeAction, Func<object, bool> canExecute)
        {

            if (executeAction != null) this._executeAction = executeAction;
            if (canExecute != null) this.CanExecuteHandler = canExecute;
        }

        #endregion Constructor

        #region Methods

        public bool CanExecute(object parameter)
        {
            bool result = true;
            Func<object, bool> canExecuteHandler = this.CanExecuteHandler;
            if (canExecuteHandler != null)
            {
                result = canExecuteHandler(parameter);
            }

            return result;
        }

        public void RaiseCanExecuteChanged()
        {
            EventHandler handler = this.CanExecuteChanged;
            if (handler != null)
            {
                handler(this, new EventArgs());
            }
        }

        public void Execute(object source)
        {
            if (this._executeAction != null)
                this._executeAction(source);

            var handler = this.Executed;
            if (handler != null)
            {
                handler(source, new CommandArgs(null));
            }
        }
        public void Execute(object source, object parameter)
        {
            if (this._executeAction != null)
                this._executeAction(parameter);

            var handler = this.Executed;
            if (handler != null)
            {
                handler(source, new CommandArgs(parameter));
            }
        }

        #endregion Methods

        #region Events

        public event EventHandler CanExecuteChanged;
        public event EventHandler<CommandArgs> Executed;

        #endregion Events

        #region Properties
        public Func<object, bool> CanExecuteHandler
        {
            get { return this._canExecute; }
            set
            {
                if (value == this._canExecute) return;
                this._canExecute = value;
                this.RaiseCanExecuteChanged();
            }
        }
        #endregion
    }
}
